package com.youth.fund.hk.hostManager.lucene.core;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.beans.factory.annotation.Value;

import com.youth.fund.hk.hostManager.lucene.datamodel.ContentModel;
import com.youth.fund.hk.hostManager.lucene.webcontent.PackContentObject;

public class SearchEngineCore {
	private static SearchEngineCore instance;

	private final static Version version = Version.LATEST;

	public static SearchEngineCore getInstance() {
		if (instance == null) {
			instance = new SearchEngineCore();
		}
		return instance;
	}
	public static SearchEngineCore getInstance(String index_path) {
		if (instance == null) {
			instance = new SearchEngineCore(index_path);
		}
		return instance;
	}

	private SearchEngineCore(String index_path) {
		this.index_path = index_path;
		
		
		
		try {
			// 创建索引路径
			dir = FSDirectory.open(new File(this.index_path));

			// 创建解析器
			analyzer = new CJKAnalyzer();

			// indexwriter配置
			config = new IndexWriterConfig(version, analyzer);

			config.setMaxBufferedDocs(10000);

			config.setRAMBufferSizeMB(20);

			config.setOpenMode(OpenMode.CREATE_OR_APPEND);

			if (IndexWriter.isLocked(dir)) {
				IndexWriter.unlock(dir);
			}
			// 创建IndexWriter
			writer = new IndexWriter(dir, config);

			writer.commit();

			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private SearchEngineCore() {

		try {
			// 创建索引路径
			dir = FSDirectory.open(new File(this.index_path));

			// 创建解析器
			analyzer = new CJKAnalyzer();

			// indexwriter配置
			config = new IndexWriterConfig(version, analyzer);

			config.setMaxBufferedDocs(10000);

			config.setRAMBufferSizeMB(20);

			config.setOpenMode(OpenMode.CREATE_OR_APPEND);

			if (IndexWriter.isLocked(dir)) {
				IndexWriter.unlock(dir);
			}
			// 创建IndexWriter
			writer = new IndexWriter(dir, config);

			writer.commit();

			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	
	private String index_path ;

	private Directory dir;

	private Analyzer analyzer;

	private IndexWriter writer;

	private IndexWriterConfig config;

	private IndexReader reader;

	private IndexSearcher searcher;

	private QueryParser parser;

	public boolean addIndex(Document doc) {
		boolean result = false;

		try {
			writer.addDocument(doc);

			writer.commit();

			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);

			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}

	public boolean deleteIndex(Document doc) {
		boolean result = false;

		try {
			writer.deleteDocuments(new Term("url", doc.get("url")));

			writer.commit();

			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);
			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}

	public boolean updateIndex(Document doc) {
		boolean result = false;

		try {
			writer.updateDocument(new Term("url", doc.get("url")), doc);

			writer.commit();

			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);

			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}

	public boolean deleteAll() {
		boolean result = false;

		try {
			writer.deleteAll();

			writer.commit();

			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);

			result = true;
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}

	public List<Document> queryIndex(String keyword) {
		List<Document> result = new ArrayList<Document>();

		keyword = keyword.trim();

		if (keyword == null || keyword.length() == 0 || "".equalsIgnoreCase(keyword)) {
			return result;
		}

		String[] fields = { "title", "url", "content" };

		parser = new MultiFieldQueryParser(fields, analyzer);

		try {
			
			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);
			
			Query query = parser.parse(keyword);

			BooleanQuery boolquery = new BooleanQuery();

			boolquery.add(query, Occur.MUST);

			TopScoreDocCollector collector = TopScoreDocCollector.create(10000,
					true);

			searcher.search(boolquery, collector);

			TopDocs docs = collector.topDocs();

			int resultHits = docs.totalHits;

			for (int i = 0; i < resultHits; i++) 
			{
				Document temp = searcher.doc(docs.scoreDocs[i].doc);

				result.add(temp);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}
	
	public List<ContentModel> queryIndexHighLighter(String keyword) {
		List<ContentModel> result = new ArrayList<ContentModel>();

		keyword = keyword.trim();

		if (keyword == null || keyword.length() == 0 || "".equalsIgnoreCase(keyword)) {
			return result;
		}

		String[] fields = { "title", "url", "content" };

		parser = new MultiFieldQueryParser(fields, analyzer);

		try {
			
			reader = DirectoryReader.open(dir);

			searcher = new IndexSearcher(reader);
			
			Query query = parser.parse(keyword);

			BooleanQuery boolquery = new BooleanQuery();

			boolquery.add(query, Occur.MUST);

			TopScoreDocCollector collector = TopScoreDocCollector.create(10000,
					true);

			searcher.search(boolquery, collector);

			TopDocs docs = collector.topDocs();

			int resultHits = docs.totalHits;

			for (int i = 0; i < resultHits; i++) 
			{
				Document temp = searcher.doc(docs.scoreDocs[i].doc);

				result.add(PackContentObject.convertDocToContentWithLighter(temp, query, analyzer));
			}
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}
}
